package com.jumi.microservice.wdt;

import com.google.common.base.CaseFormat;
import com.jumi.microservice.common.enumeration.CommonResponseEnum;
import com.jumi.microservice.common.exception.BaseException;
import com.jumi.microservice.domain.GoodsSkuMaterialDTO;
import com.jumi.microservice.dto.wdt.WdtGoodsRequest;
import com.jumi.microservice.dto.wdt.WdtLogisticsRequest;
import com.jumi.microservice.dto.wdt.WdtOrderRequest;
import com.jumi.microservice.entity.AfterSealOrder;
import com.jumi.microservice.entity.AfterSealOrderGoods;
import com.jumi.microservice.service.BasicDataService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Dirk
 * @Date 2020-08-18 14:26
 */
@Component
public class WdtRequestConvert {

    @Reference
    private BasicDataService basicDataService;

    public WdtOrderRequest wdtOrderRequestConvert(AfterSealOrder afterSealOrder) {
        WdtOrderRequest wdtOrderRequest = new WdtOrderRequest();
        wdtOrderRequest.setTid(afterSealOrder.getOrderNo());
        wdtOrderRequest.setTradeStatus(new Byte("30"));
        wdtOrderRequest.setPayStatus(new Byte("2"));
        wdtOrderRequest.setDeliveryTerm(new Byte("1"));
        wdtOrderRequest.setTradeTime(afterSealOrder.getCreateTime());
        wdtOrderRequest.setBuyerNick(afterSealOrder.getReceiverName());
        wdtOrderRequest.setReceiverName(afterSealOrder.getReceiverName());
        wdtOrderRequest.setReceiverAddress(afterSealOrder.getReceiverAddress());
        wdtOrderRequest.setReceiverMobile(afterSealOrder.getReceiverPhone());
        // 默认选择中通速递
        wdtOrderRequest.setLogisticsType(new Byte("5"));
        wdtOrderRequest.setPostAmount(BigDecimal.ZERO);
        wdtOrderRequest.setCodAmount(BigDecimal.ZERO);
        wdtOrderRequest.setExtCodFee(BigDecimal.ZERO);
        wdtOrderRequest.setOtherAmount(BigDecimal.ZERO);
        wdtOrderRequest.setPaid(BigDecimal.ZERO);
        return wdtOrderRequest;
    }

    public List<WdtGoodsRequest> wdtGoodsRequestsConvert(List<AfterSealOrderGoods> afterSealOrderGoodsList) {
        List<WdtGoodsRequest> wdtGoodsRequestList = new ArrayList<>();
        List<Long> skuIds = afterSealOrderGoodsList.stream()
                .map(AfterSealOrderGoods::getGoodsId)
                .map(Integer::longValue)
                .collect(Collectors.toList());
        List<GoodsSkuMaterialDTO> goodsSkuMaterialDTOList = basicDataService.getMaterialSkuRelationshipByIds(skuIds);
        afterSealOrderGoodsList.forEach(logisticsGoods -> {
            goodsSkuMaterialDTOList.stream()
                    .filter(goodsSkuMaterialDTO -> goodsSkuMaterialDTO.getSkuId().equals(logisticsGoods.getGoodsId().longValue()))
                    .findFirst()
                    .orElse(new GoodsSkuMaterialDTO())
                    .getMaterialSkuRelationship()
                    .forEach(materialSkuRelationshipDTO -> {
                        WdtGoodsRequest wdtGoodsRequest = new WdtGoodsRequest();
                        wdtGoodsRequest.setOid("JMT_".concat(logisticsGoods.getId().toString())
                                .concat(materialSkuRelationshipDTO.getMaterialSkuId().toString()));
                        wdtGoodsRequest.setNum(new BigDecimal(logisticsGoods.getGoodsAmount())
                                .multiply(new BigDecimal(materialSkuRelationshipDTO.getComposeNumber())));
                        wdtGoodsRequest.setPrice(BigDecimal.ZERO);
                        wdtGoodsRequest.setStatus(new Byte("30"));
                        wdtGoodsRequest.setRefundStatus(new Byte("0"));
                        wdtGoodsRequest.setGoodsId(materialSkuRelationshipDTO.getWdtGoodsId().toString());
                        wdtGoodsRequest.setGoodsNo(materialSkuRelationshipDTO.getMaterialSpuCode());
                        wdtGoodsRequest.setSpecNo(materialSkuRelationshipDTO.getMaterialSkuCode());
                        wdtGoodsRequest.setGoodsName(materialSkuRelationshipDTO.getMaterialSpuName());
                        wdtGoodsRequest.setAdjustAmount(BigDecimal.ZERO);
                        wdtGoodsRequest.setDiscount(BigDecimal.ZERO);
                        wdtGoodsRequest.setShareDiscount(BigDecimal.ZERO);
                        wdtGoodsRequestList.add(wdtGoodsRequest);
                    });
        });
        return wdtGoodsRequestList;
    }

    /**
     * object -> map
     * map的key使用下划线命名规则
     *
     * @param obj
     * @return
     */
    public Map<String, Object> objectToMap(Object obj) {
        assert obj != null;
        Map<String, Object> map = new HashMap<>(8);
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        try {
            for (Field field : declaredFields) {
                int mod = field.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                field.setAccessible(true);
                map.put(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName()), field.get(obj));
            }
        } catch (Exception e) {
            throw new BaseException(CommonResponseEnum.SERVER_ERROR.getCode(), e.getMessage());
        }
        return map;
    }

    public List<Map<String, Object>> orderListConvert(List<WdtOrderRequest> requestList) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        requestList.forEach(wdtOrderRequest -> {
            Map<String, Object> map = objectToMap(wdtOrderRequest);
            map.put("order_list", goodsListConvert(wdtOrderRequest.getOrderList()));
            mapList.add(map);
        });
        return mapList;
    }

    public List<Map<String, Object>> goodsListConvert(List<WdtGoodsRequest> requestList) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        requestList.forEach(wdtGoodsRequest -> {
            mapList.add(objectToMap(wdtGoodsRequest));
        });
        return mapList;
    }

    public List<Map<String, Object>> logisticsListConvert(List<WdtLogisticsRequest> requestList) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        requestList.forEach(wdtLogisticsRequest -> {
            mapList.add(objectToMap(wdtLogisticsRequest));
        });
        return mapList;
    }
}
